from flask_restful import Resource, marshal
from sqlalchemy import or_, desc, func, and_

from app.exception import APIException, USER_NOT_EXISTS, BANNER_NOT_EXISTS, BRANCH_NOT_EXISTS, BRAND_NOT_EXISTS, \
    CATEGORY_NOT_EXISTS, GOODS_NOT_EXISTS, ORDER_NOT_EXISTS, DATABASE_ERROR, BRAND_NOT_NULL, CATEGORY_NOT_NULL, \
    USERNAME_OR_PHONE_IS_EXISTS, USER_IS_DELETED, INFO_NOT_EXISTS, BRANCH_NOT_NULL, TAG_NOT_EXISTS, \
    FEE_TEMPLATE_NOT_EXISTS, ATTR_ALREADY_EXISTS, INFO_ALREADY_EXISTS
from app.api.admin.fields import admin_user_fields, banner_fields, branch_fields, brand_fields, user_fields, \
    category_fields, order_fields, goods_fields, info_fields, tag_fields, fee_template_fields, remote_area_fields, \
    attrs_fields
from app.api.admin.parsers import update_admin_user_args, get_param_parser, pagination_parser, add_admin_user_args, \
    admin_user_filter_parser, update_banner_args, add_banner_args, update_branch_args, branch_filter_parser, \
    add_branch_args, update_brand_args, add_brand_args, sort_parser, update_category_args, \
    add_category_args, add_order_args, update_order_args, add_goods_args, update_goods_args, user_filter_parser, \
    order_filter_parser, date_filter_parser, goods_filter_parser, update_goods_info_args, add_goods_info_args, \
    update_tag_args, add_tag_args, add_fee_template_args, update_fee_template_args, add_remote_area_args, add_attr_args
from app.extensions import roles_accepted, auth, db
from app.models import AdminUser, Banner, Branch, Brand, User, Category, Order, Goods, GoodsPicture, GoodsInfo, \
    GoodsRecord, Tag, FeeTemplate, RemoteArea, Attribute, GoodsSku, GoodsSkuAttribute, GoodsSkuStock, \
    SecondaryCategory


class AdminUserResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def user_exist(user_id):
        user = AdminUser.query.get(user_id)
        if not user:
            # abort(404, message='用户(id=%s)不存在' % user_id, code=404)
            raise APIException(USER_NOT_EXISTS)
        if user.deleted == 1:
            raise APIException(USER_IS_DELETED)
        return user

    def get(self, user_id):
        """ 获取用户信息 """
        user = self.user_exist(user_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(user, admin_user_fields)
               }, 200

    def put(self, user_id):
        # if g.user.role != 'admin' and g.user.id != user_id:
        #     raise APIException(403, '没有权限')
        user = self.user_exist(user_id)
        args = update_admin_user_args.parse_args()
        password = args.pop('password')
        if password:
            user.set_password(password)
        user.update(True, **args)
        return {
                   'code': 0,
                   'message': '更新成功',
                   'data': marshal(user, admin_user_fields)
               }, 200

    def delete(self, user_id):
        user = self.user_exist(user_id)

        user.update(True, locked=1)
        user.update(True, deleted=1)
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class AdminUsersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = AdminUser.query

        _filter = args.get('filter')
        if _filter:
            filter_args = admin_user_filter_parser.parse_args(req=args)
            keyword = filter_args.pop('keyword')
            if keyword:
                query = query.filter(
                    or_(AdminUser.username.like("%" + keyword + "%"), AdminUser.real_name.like("%" + keyword + "%")))
            else:
                for k, v in filter_args.items():
                    if v is not None:
                        query = query.filter(getattr(AdminUser, k).like("%" + v + "%"))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _users = query.paginate(page, per_page=per_page, error_out=False)
        # if page > _users.pages:
        #     abort(400, message="page no can't max than pages, no users data!",
        #           error_date=fmt_date(datetime.datetime.now()))
        # if not _users.items:
        #     abort(404, message="no users data!", error_date=fmt_date(datetime.datetime.now()))

        users = {
            'data': marshal(_users.items, admin_user_fields),
            "pageSize": _users.per_page,
            "pageNo": _users.page,
            "totalPage": _users.pages,
            "totalCount": _users.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': users
               }, 200

    def post(self):
        args = add_admin_user_args.parse_args()

        username = args.get('username')
        phone_number = args.get('phone_number')
        user = AdminUser.query.filter(
            db.or_(AdminUser.phone_number == phone_number, AdminUser.username == username)).first()
        if user:
            raise APIException(USERNAME_OR_PHONE_IS_EXISTS)
        user = AdminUser.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(user, admin_user_fields)
               }, 201


class BannerResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def banner_exist(banner_id):
        banner = Banner.query.get(banner_id)
        if not banner:
            raise APIException(BANNER_NOT_EXISTS)
        return banner

    def get(self, banner_id):
        """ 获取轮播图信息 """
        banner = self.banner_exist(banner_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(banner, banner_fields)
               }, 200

    def put(self, banner_id):
        banner = self.banner_exist(banner_id)
        args = update_banner_args.parse_args()
        banner.update(True, **args)
        return {
                   'code': 0,
                   'message': '更新成功',
                   'data': marshal(banner, banner_fields)
               }, 200

    def delete(self, banner_id):
        banner = self.banner_exist(banner_id)

        banner.update(True, deleted=1)
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class BannersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Banner.query

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _banners = query.paginate(page, per_page=per_page, error_out=False)

        banners = {
            'data': marshal(_banners.items, banner_fields),
            "pageSize": _banners.per_page,
            "pageNo": _banners.page,
            "totalPage": _banners.pages,
            "totalCount": _banners.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': banners
               }, 200

    def post(self):
        args = add_banner_args.parse_args()

        banner = Banner.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(banner, banner_fields)
               }, 201


class BranchResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def branch_exist(branch_id):
        branch = Branch.query.get(branch_id)
        if not branch:
            raise APIException(BRANCH_NOT_EXISTS)
        return branch

    def get(self, branch_id):
        branch = self.branch_exist(branch_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(branch, branch_fields)
               }, 200

    def put(self, branch_id):
        branch = self.branch_exist(branch_id)
        args = update_branch_args.parse_args()
        branch.update(True, **args)

        return {
                   'code': 0,
                   'message': '更新成功',
                   'data': marshal(branch, branch_fields)
               }, 200

    def delete(self, branch_id):
        branch = self.branch_exist(branch_id)
        user = AdminUser.query.filter_by(branch_id=branch_id).all()
        if user:
            raise APIException(BRANCH_NOT_NULL)
        branch.update(True, deleted=1)
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class BranchesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Branch.query

        _filter = args.get('filter')
        if _filter:
            filter_args = branch_filter_parser.parse_args(req=args)
            keyword = filter_args.pop('keyword')
            if keyword:
                query = query.filter(
                    or_(Branch.name.like("%" + keyword + "%"), Branch.manager.like("%" + keyword + "%")))
            else:
                for k, v in filter_args.items():
                    if v is not None:
                        query = query.filter(getattr(Branch, k).like("%" + v + "%"))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _branches = query.paginate(page, per_page=per_page, error_out=False)

        branches = {
            'data': marshal(_branches.items, branch_fields),
            "pageSize": _branches.per_page,
            "pageNo": _branches.page,
            "totalPage": _branches.pages,
            "totalCount": _branches.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': branches
               }, 200

    def post(self):
        args = add_branch_args.parse_args()

        branch = Branch.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(branch, branch_fields)
               }, 201


class BrandResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def brand_exist(brand_id):
        brand = Brand.query.get(brand_id)
        if not brand:
            raise APIException(BRAND_NOT_EXISTS)
        return brand

    def get(self, brand_id):
        brand = self.brand_exist(brand_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(brand, brand_fields)
               }, 200

    def put(self, brand_id):
        brand = self.brand_exist(brand_id)
        args = update_brand_args.parse_args()
        brand.update(True, **args)

        return {
                   'code': 0,
                   'message': '更新成功',
                   'data': marshal(brand, brand_fields)
               }, 200

    def delete(self, brand_id):
        brand = self.brand_exist(brand_id)
        goods = Goods.query.filter_by(brand_id=brand_id).all()
        if goods:
            raise APIException(BRAND_NOT_NULL)
        brand.delete()
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class BrandsResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Brand.query.filter_by(deleted=0)

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Brand, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _brands = query.paginate(page, per_page=per_page, error_out=False)

        brands = {
            'data': marshal(_brands.items, brand_fields),
            "pageSize": _brands.per_page,
            "pageNo": _brands.page,
            "totalPage": _brands.pages,
            "totalCount": _brands.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': brands
               }, 200

    def post(self):
        args = add_brand_args.parse_args()

        brand = Brand.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(brand, brand_fields)
               }, 201


class CategoryResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def category_exist(category_id):
        category = Category.query.get(category_id)
        if not category:
            raise APIException(CATEGORY_NOT_EXISTS)
        return category

    def get(self, category_id):
        category = self.category_exist(category_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(category, category_fields)
               }, 200

    def put(self, category_id):
        category = self.category_exist(category_id)
        args = update_category_args.parse_args()
        category.update(True, **args)

        return {
                   'code': 0,
                   'message': '更新成功',
                   'data': marshal(category, category_fields)
               }, 200

    def delete(self, category_id):
        category = self.category_exist(category_id)
        # category.update(True, deleted=1)
        # 判断分类下是否有商品
        goods = Goods.query.filter_by(category_id=category_id).all()
        if goods:
            raise APIException(CATEGORY_NOT_NULL)
        category.delete()
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class CategoriesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Category.query

        query = query.order_by(desc(Category.sort))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _categories = query.paginate(page, per_page=per_page, error_out=False)

        categories = {
            'data': marshal(_categories.items, category_fields),
            "pageSize": _categories.per_page,
            "pageNo": _categories.page,
            "totalPage": _categories.pages,
            "totalCount": _categories.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': categories
               }, 200

    def post(self):
        args = add_category_args.parse_args()

        category = Category.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(category, category_fields)
               }, 201


class GoodsResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def goods_exist(goods_id):
        goods = Goods.query.get(goods_id)
        if not goods:
            raise APIException(GOODS_NOT_EXISTS)
        return goods

    def get(self, goods_id):
        goods = self.goods_exist(goods_id)
        tree_sql = 'select k_id, k_name from t_goods_sku_attribute where sku_id in (select id from t_goods_sku ' \
                   'WHERE goods_id = %s) group by k_id' % goods_id
        results = db.session.execute(tree_sql).fetchall()

        sku_attrs = [dict(zip(result.keys(), result)) for result in results]

        for value in sku_attrs:
            sql2 = 'select v_id, v_name from t_goods_sku_attribute where sku_id in ' \
                   '(select id from t_goods_sku WHERE goods_id = :goods_id) and k_id = :k_id ' \
                   'group by k_id, v_id  ORDER BY v_id'
            result = db.session.execute(sql2, {'goods_id': goods_id, 'k_id': value['k_id']}).fetchall()
            value['values'] = result
        goods.sku_attrs = sku_attrs
        return {
           'code': 0,
           'message': '',
           'data': marshal(goods, goods_fields)
        }, 200

    def put(self, goods_id):
        goods = self.goods_exist(goods_id)
        args = update_goods_args.parse_args()

        images = args.pop('images', [])
        # tids = args.pop('tids', [])
        skus = args.pop('skus', [])

        goods.update(False, **args)

        if images:
            for image in images:
                if image.get('id'):
                    pic = GoodsPicture.query.get(image.get('id'))
                    if image.get('deleted'):
                        pic.delete(False, )
                    else:
                        pic.update(False, **image)
                else:
                    image['goods_id'] = goods.id
                    GoodsPicture.create(False, **image)


        # 如果修改了规格属性 需要重新添加sku商品组合
        sku_ids = []
        for sku in skus:
            if sku['price'] == 0:
                continue
            attrs = sku.pop('attrs')
            sku['goods_id'] = goods.id

            if sku.get('sku_id', 0):
                goods_sku = GoodsSku.query.get(sku['sku_id'])
                goods_sku.update(False, **sku)
                sku_ids.append(sku['sku_id'])
            else:
                goods_sku = GoodsSku.create(False, **sku)
                sku_ids.append(goods_sku.id)

                for attr in attrs:
                    attr['sku_id'] = goods_sku.id
                    GoodsSkuAttribute.create(False, **attr)

        GoodsSku.query.filter(and_(GoodsSku.id.notin_(sku_ids), GoodsSku.goods_id == goods.id))\
            .delete(synchronize_session=False)

        try:
            db.session.execute('delete from t_goods_sku_stock where sku_id not in (SELECT id from t_goods_sku)')
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(goods, goods_fields)
        }, 200

    def delete(self, goods_id):
        goods = self.goods_exist(goods_id)
        goods.update(True, deleted=1)
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class GoodsListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Goods.query.filter_by(deleted=0).order_by(Goods.created.desc())

        _filter = args.get('filter')
        if _filter:
            filter_args = goods_filter_parser.parse_args(req=args)
            name = filter_args.pop('name')
            if name:
                query = query.filter(Goods.name.like('%' + name + '%'))
            for k, v in filter_args.items():
                if v is not None:
                    query = query.filter(getattr(Goods, k) == v)

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Goods, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _goods = query.paginate(page, per_page=per_page, error_out=False)

        goods = {
            'data': marshal(_goods.items, goods_fields),
            "pageSize": _goods.per_page,
            "pageNo": _goods.page,
            "totalPage": _goods.pages,
            "totalCount": _goods.total
        }

        return {
           'code': 0,
           'message': '',
           'data': goods
        }, 200

    def post(self):
        args = add_goods_args.parse_args()

        images = args.pop('images')
        skus = args.pop('skus', [])

        goods = Goods.create(False, **args)

        for image in images:
            image['goods_id'] = goods.id
            GoodsPicture.create(False, **image)

        for sku in skus:
            if sku['price'] == 0:
                continue
            attrs = sku.pop('attrs')
            sku['goods_id'] = goods.id
            goods_sku = GoodsSku.create(False, **sku)
            for attr in attrs:
                attr['sku_id'] = goods_sku.id
                GoodsSkuAttribute.create(False, **attr)

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(goods, goods_fields)
        }, 201


class OrderResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'manager'), auth.login_required]

    @staticmethod
    def order_exist(order_id):
        order = Order.query.get(order_id)
        if not order:
            raise APIException(ORDER_NOT_EXISTS)
        return order

    def get(self, order_id):
        order = self.order_exist(order_id)
        if order.order_sku.sku:
            order.goods.pic_url = order.order_sku.sku.cover
        return {
           'code': 0,
           'message': '',
           'data': marshal(order, order_fields)
        }, 200

    def put(self, order_id):
        order = self.order_exist(order_id)
        args = update_order_args.parse_args()
        order.update(True, **args)

        if order.order_sku.sku:
            order.goods.pic_url = order.order_sku.sku.cover

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(order, order_fields)
        }, 200

    def delete(self, order_id):
        order = self.order_exist(order_id)
        # order.update(True, deleted=1)
        order.delete(True)
        return {
                   'code': 0,
                   'message': '删除成功'
               }, 200


class OrdersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Order.query

        _filter = args.get('filter')
        if _filter:
            filter_args = order_filter_parser.parse_args(req=args)
            order_no = filter_args.pop('order_no')
            if order_no:
                query = query.filter(Order.order_no.like('%' + order_no + '%'))

            for k, v in filter_args.items():
                if v is not None:
                    query = query.filter(getattr(Order, k) == v)

            date_filter_args = date_filter_parser.parse_args(req=args)
            start_date = date_filter_args.get('start_date')
            end_date = date_filter_args.get('end_date')
            if start_date:
                if end_date is None:
                    end_date = start_date
                query = query.filter((func.date(Order.order_time)).between(start_date, end_date))

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Order, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _orders = query.paginate(page, per_page=per_page, error_out=False)

        for order in _orders.items:
            if order.order_sku.sku:
                order.goods.pic_url = order.order_sku.sku.cover

        orders = {
            'data': marshal(_orders.items, order_fields),
            "pageSize": _orders.per_page,
            "pageNo": _orders.page,
            "totalPage": _orders.pages,
            "totalCount": _orders.total
        }

        return {
           'code': 0,
           'message': '',
           'data': orders
        }, 200

    def post(self):
        args = add_order_args.parse_args()

        order = Order.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(order, order_fields)
        }, 201


class UserResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    def get(self, user_id):
        pass

    def put(self, user_id):
        pass

    def delete(self, user_id):
        pass


class UsersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin', 'manager'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = User.query

        _filter = args.get('filter')
        if _filter:
            filter_args = user_filter_parser.parse_args(req=args)
            uid = filter_args.pop('uid')
            if uid is not None:
                query = query.filter_by(uid=uid)
                user = query.first()
                if user:
                    return {
                               'code': 0,
                               'message': '',
                               'data': marshal(user, user_fields)
                           }, 200
                else:
                    raise APIException(USER_NOT_EXISTS)
            keyword = filter_args.pop('keyword')
            if keyword is not None:
                query = query.filter(
                    or_(User.nickname.like("%" + keyword + "%"), User.uid.like("%" + keyword + "%")))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _users = query.paginate(page, per_page=per_page, error_out=False)

        users = {
            'data': marshal(_users.items, user_fields),
            "pageSize": _users.per_page,
            "pageNo": _users.page,
            "totalPage": _users.pages,
            "totalCount": _users.total
        }

        return {
                   'code': 0,
                   'message': '',
                   'data': users
               }, 200

    def post(self):
        pass


class UserAddressResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    def get(self, address_id):
        pass

    def put(self, address_id):
        pass

    def delete(self, address_id):
        pass


class UserAddressesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        pass

    def post(self):
        pass


class GoodsInfoResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def info_exist(info_id):
        info = GoodsInfo.query.get(info_id)
        if not info:
            raise APIException(INFO_NOT_EXISTS)
        return info

    def get(self, info_id):
        info = self.info_exist(info_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(info, info_fields)
        }, 200

    def put(self, info_id):
        info = self.info_exist(info_id)
        args = update_goods_info_args.parse_args()

        sku_stock = args.pop('sku_stock')
        increment = args.get('stock')
        args['stock'] = info.stock + increment

        stock = 0
        total_stock = 0

        if sku_stock:
            for item in sku_stock:
                goods_sku_stock = GoodsSkuStock.query.filter(and_(GoodsSkuStock.sku_id == item['id'],
                                                                  GoodsSkuStock.goods_info_id == info.id)).first()
                if goods_sku_stock:
                    goods_sku_stock.stock += item['stock']
                    goods_sku_stock.update(False, )
                    stock += item['stock']
                    total_stock += goods_sku_stock.stock
                else:
                    row = {
                        'goods_info_id': info.id,
                        'sku_id': item['id'],
                        'stock': item['stock']
                    }
                    GoodsSkuStock.create(False, **row)
                    stock += item['stock']
                    total_stock += item['stock']

        if stock > 0:
            args['stock'] = total_stock
            increment = stock

        info.update(False, **args)

        row = {
            'stock_id': info.id,
            'type': 1,
            'increment': increment
        }

        GoodsRecord.create(False, **row)

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(info, info_fields)
        }, 200

    def delete(self, info_id):
        pass


class GoodsInfosResource(Resource):
    methods = ['OPTIONS', 'GET']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self, goods_id):
        args = get_param_parser.parse_args()

        query = GoodsInfo.query.filter_by(goods_id=goods_id)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _info = query.paginate(page, per_page=per_page, error_out=False)

        info = {
            'data': marshal(_info.items, info_fields),
            "pageSize": _info.per_page,
            "pageNo": _info.page,
            "totalPage": _info.pages,
            "totalCount": _info.total
        }

        return {
           'code': 0,
           'message': '',
           'data': info
        }, 200


class GoodsInfoListResource(Resource):
    methods = ['OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def post(self):
        args = add_goods_info_args.parse_args()

        info = GoodsInfo.query.filter(and_(GoodsInfo.branch_id == args['branch_id'],
                                           GoodsInfo.goods_id == args['goods_id'])).first()
        if info:
            raise APIException(INFO_ALREADY_EXISTS)
        sku_stock = args.pop('sku_stock')
        increment = args.get('stock')
        info = GoodsInfo.create(False, **args)

        stock = 0

        if sku_stock:
            for item in sku_stock:
                row = {
                    'goods_info_id': info.id,
                    'sku_id': item['id'],
                    'stock': item['stock']
                }
                GoodsSkuStock.create(False, **row)
                stock += item['stock']

        if stock > 0:
            info.update(False, stock=stock)
            increment = stock

        row = {
            'stock_id': info.id,
            'type': 1,
            'increment': increment
        }

        GoodsRecord.create(False, **row)

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(info, info_fields)
        }, 201


class TagResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('admin'), auth.login_required]

    @staticmethod
    def tag_exist(tag_id):
        tag = Tag.query.get(tag_id)
        if not tag:
            raise APIException(TAG_NOT_EXISTS)
        return tag

    def put(self, tag_id):
        tag = self.tag_exist(tag_id)
        args = update_tag_args.parse_args()
        tag.update(True, **args)

        return {
            'code': 0,
            'message': '更新成功',
            'data': marshal(tag, tag_fields)
        }, 200


class TagListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Tag.query

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Tag, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _tags = query.paginate(page, per_page=per_page, error_out=False)

        tags = {
            'data': marshal(_tags.items, tag_fields),
            "pageSize": _tags.per_page,
            "pageNo": _tags.page,
            "totalPage": _tags.pages,
            "totalCount": _tags.total
        }

        return {
           'code': 0,
           'message': '',
           'data': tags
        }, 200

    def post(self):
        args = add_tag_args.parse_args()

        tag = Tag.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(tag, tag_fields)
        }, 201


class FeeTemplateResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT']
    decorators = [roles_accepted('admin'), auth.login_required]

    @staticmethod
    def fee_template_exist(fee_template_id):
        fee_template = FeeTemplate.query.get(fee_template_id)
        if not fee_template:
            raise APIException(FEE_TEMPLATE_NOT_EXISTS)
        return fee_template

    def put(self, fee_template_id):
        fee_template = self.fee_template_exist(fee_template_id)
        args = update_fee_template_args.parse_args()
        fee_template.update(True, **args)

        return {
            'code': 0,
            'message': '更新成功',
            'data': marshal(fee_template, fee_template_fields)
        }, 200


class FeeTemplateListResource(Resource):
    methods = ['GET', 'OP.'
                      'TIONS', 'POST']
    decorators = [roles_accepted('admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = FeeTemplate.query

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(FeeTemplate, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _templates = query.paginate(page, per_page=per_page, error_out=False)

        templates = {
            'data': marshal(_templates.items, fee_template_fields),
            "pageSize": _templates.per_page,
            "pageNo": _templates.page,
            "totalPage": _templates.pages,
            "totalCount": _templates.total
        }

        return {
           'code': 0,
           'message': '',
           'data': templates
        }, 200

    def post(self):
        args = add_fee_template_args.parse_args()

        fee_template = FeeTemplate.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(fee_template, fee_template_fields)
        }, 201


class RemoteAreaListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('admin'), auth.login_required]

    def get(self):
        areas = RemoteArea.query.all()

        return {
           'code': 0,
           'message': '',
           'data': marshal(areas, remote_area_fields)
        }, 200

    def post(self):
        args = add_remote_area_args.parse_args()

        areas = args.pop('areas')

        db.session.execute('truncate table t_remote_area')

        for area in areas:
            RemoteArea.create(True, **area)

        return {
           'code': 0,
           'message': '创建成功',
           'data': []
        }, 201


class AttributeListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('admin'), auth.login_required]

    def get(self):
        attrs = Attribute.query.all()

        return {
           'code': 0,
           'message': '',
           'data': marshal(attrs, attrs_fields)
        }, 200

    def post(self):
        args = add_attr_args.parse_args()

        attr = Attribute.query.filter_by(name=args['name']).first()

        if attr:
            raise APIException(ATTR_ALREADY_EXISTS)

        Attribute.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': []
        }, 201


class SecondaryCategoryResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def category_exist(category_id):
        category = SecondaryCategory.query.get(category_id)
        if not category:
            raise APIException(CATEGORY_NOT_EXISTS)
        return category

    def get(self, category_id):
        category = self.category_exist(category_id)
        return {
                   'code': 0,
                   'message': '',
                   'data': marshal(category, category_fields)
               }, 200

    def put(self, category_id):
        category = self.category_exist(category_id)
        args = update_category_args.parse_args()
        category.update(True, **args)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(category, category_fields)
        }, 200

    def delete(self, category_id):
        category = self.category_exist(category_id)
        # category.update(True, deleted=1)
        # 判断分类下是否有商品
        goods = Goods.query.filter_by(category_id=category_id).all()
        if goods:
            raise APIException(CATEGORY_NOT_NULL)
        category.delete()
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class SecondaryCategoriesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = SecondaryCategory.query

        query = query.order_by(desc(SecondaryCategory.sort))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _categories = query.paginate(page, per_page=per_page, error_out=False)

        categories = {
            'data': marshal(_categories.items, category_fields),
            "pageSize": _categories.per_page,
            "pageNo": _categories.page,
            "totalPage": _categories.pages,
            "totalCount": _categories.total
        }

        return {
           'code': 0,
           'message': '',
           'data': categories
        }, 200

    def post(self):
        args = add_category_args.parse_args()

        category = SecondaryCategory.create(**args)

        return {
                   'code': 0,
                   'message': '创建成功',
                   'data': marshal(category, category_fields)
               }, 201
